package opf5.entities.partidos;


import java.util.ArrayList;
import java.util.List;

import opf5.entities.dominio.Equipo;
import opf5.entities.dominio.Inscripcion;
import opf5.entities.dominio.Jugador;
import opf5.entities.dominio.Partido;
import opf5.entities.excepciones.OperacionNoPermitidaException;
import opf5.entities.repositorios.OPF5Factory;
import opf5.utilidades.Fecha;

public class PartidoConcreto implements Partido {
	List<Inscripcion> inscripciones = new ArrayList<Inscripcion>(10);
	List<Equipo> equipos = new ArrayList<Equipo>(2);
	private Fecha fecha;
	private String lugar;
	private EstadoPartido estadoPartido;
	
	public PartidoConcreto(Fecha fecha, String lugar) {
		this.fecha = fecha;
		this.lugar = lugar;
		this.equipos.add(null);
		this.equipos.add(null);
		this.setEstado(new EstadoInscripcionesAbiertas());
	}

	@Override
	public int cantidadJugadoresInscriptos() {
		return inscripciones.size();
	}

	@Override
	public void inscribir(Inscripcion nuevaInscripcion) {
		this.estadoPartido.validarInscripcion();
		
		confirmarJugadorNoInscripto(nuevaInscripcion);
		nuevaInscripcion.confirmarVacante(this);
		agregarInscripcion(nuevaInscripcion);
	}

	private void agregarInscripcion(Inscripcion nuevaInscripcion) {
		inscripciones.add(nuevaInscripcion);
	}


	private void confirmarJugadorNoInscripto(Inscripcion nuevaInscripcion) {
		if(estaInscripto(nuevaInscripcion.getJugador()))
			throw (new OperacionNoPermitidaException("El jugador ya esta inscripto"
					+ "en el partido."));
	}

	@Override
	public boolean estaInscripto(Jugador unJugador) {
		for (Inscripcion i : inscripciones)
			if (unJugador.equals(i.getJugador()))
				return true;
		
		return false;
	}

	@Override
	public boolean hayLugar() {
		return cantidadJugadoresInscriptos() < 10;
	}

	@Override
	public List<Inscripcion> getInscripciones() {
		return inscripciones;
	}

	@Override
	public void darDeBajaSinReemplazo(Jugador unJugador) {
		this.estadoPartido.validarBaja();
		removerInscripcionDeJugador(unJugador);
		agregarInfraccionAJugador(unJugador);
	}

	private void removerInscripcionDeJugador(Jugador unJugador) {
		Inscripcion inscripcionJugador = getInscripcionJugador(unJugador);	
		inscripciones.remove(inscripcionJugador);
	}

	private Inscripcion getInscripcionJugador(Jugador unJugador) {
		Inscripcion inscripcionJugador = null;
		
		for (Inscripcion i : inscripciones) {
			if (i.getJugador().equals(unJugador)) {
				inscripcionJugador = i;
				break;
			}
		}
		
		return inscripcionJugador;
	}

	private void agregarInfraccionAJugador(Jugador unJugador) {
		unJugador.agregarInfraccion(
				OPF5Factory.getInstance().makeInfraccion(
						new Fecha(),
						"Se dio de baja sin reemplazo"));
	}

	@Override
	public void darDeBajaConReemplazo(Jugador unJugador, Jugador otroJugador) {
		this.estadoPartido.validarBaja();
		
		Inscripcion inscripcionJugador = getInscripcionJugador(unJugador);
		Inscripcion nuevaInscripcion = inscripcionJugador.copiar(otroJugador);
		confirmarJugadorNoInscripto(nuevaInscripcion);
		inscripciones.remove(inscripcionJugador);
		inscribir(nuevaInscripcion);
	}
	
	@Override
	public void confirmarEquipos(Equipo equipo1, Equipo equipo2) {
		this.estadoPartido.validarSetEquipos(this);
		
		this.equipos.clear();
		
		this.equipos.add(equipo1);
		this.equipos.add(equipo2);
		
		this.setEstado(new EstadoEquiposConfirmados());
	}

	@Override
	public List<Equipo> getEquipos() {
		return this.equipos;
	}

	@Override
	public void setResultado(int golesEquipo1, int golesEquipo2) {
		this.estadoPartido.validarSetResultado();

		this.equipos.get(0).setResultadoEquipo(golesEquipo1);
		this.equipos.get(1).setResultadoEquipo(golesEquipo2);
		
		this.setEstado(new EstadoPartidoTerminado());
	}

	@Override
	public int[] getResultados() {
		this.estadoPartido.validarGetResultados();
		
		int[] resultados = new int[2];
		resultados[0] = this.equipos.get(0).getResultado();
		resultados[1] = this.equipos.get(1).getResultado();
		
		return resultados;
	}

	@Override
	public Fecha getFechaPartido() {
		return fecha;
	}

	@Override
	public String getLugar() {
		return lugar;
	}

	@Override
	public void setFechaPartido(Fecha fecha) {
		this.estadoPartido.validarCambio();
		this.fecha = fecha;
	}

	@Override
	public void setLugarPartido(String lugar) {
		this.estadoPartido.validarCambio();
		this.lugar = lugar;
	}


	@Override
	public EstadoPartido getEstado() {
		return estadoPartido;
	}


	@Override
	public boolean estaTerminado() {
		return this.estadoPartido.getClass() == EstadoPartidoTerminado.class;
	}

	@Override
	public void setEstado(EstadoPartido estado) {
		this.estadoPartido = estado;
	}

	@Override
	public void setInscripciones(List<Inscripcion> inscripciones) {
		this.inscripciones = inscripciones;
	}

	@Override
	public void setEquipo(int numero, Equipo equipo) {
		this.equipos.set(numero, equipo);
	}
}
